#ifndef EQUATIONSOLVER_H
#define EQUATIONSOLVER_H

#include "Function.hpp"
#include <stdexcept>
#include <cmath> // 添加这个头文件以支持 std::abs

class EquationSolver {
protected:
    const Function &F;
public:
    EquationSolver(const Function& F) : F(F) {}
    virtual double solve() = 0;
};

class Bisection_Method : public EquationSolver {
private:
    double a, b;
    double eps, delta;
    int Maxiter;
public:
    Bisection_Method(const Function &F, double a, double b,
        double eps = 1e-7, double delta = 1e-6, int Maxiter = 100) :
        EquationSolver(F), a(a), b(b), eps(eps), delta(delta), Maxiter(Maxiter) {}

    virtual double solve() {
        double fa = F(a); // 计算 f(a)
        double fb = F(b); // 计算 f(b)
        double c = (a + b) / 2.0; // 初始化c

        // 检查初始区间是否有效
        if (fa * fb > 0) {
            throw std::runtime_error("The function must have different signs at the endpoints.");
        }

        for (int iter = 0; iter < Maxiter; ++iter) {
            c = (a + b) / 2.0; // 计算中点
            double fc = F(c); // 计算 f(c)

            // 检查是否满足精度要求
            if (std::abs(fc) < eps || std::abs(b - a) < delta) {
                return c; // 返回根
            }

            // 根据 f(c) 的符号选择新的区间
            if (fa * fc < 0) {
                b = c; // 根在 [a, c] 区间
                fb = fc;
            } else {
                a = c; // 根在 [c, b] 区间
                fa = fc;
            }
        }

        // 如果达到最大迭代次数
        throw std::runtime_error("Max iterations reached.");
        return c;
    }
};

class Newton_Method : public EquationSolver {
private:
    double x0;
    double eps;
    int Maxiter;
public:
    Newton_Method(const Function &F, double x0,
        double eps = 1e-7, int Maxiter = 100) : // 修改默认值
        EquationSolver(F), x0(x0), eps(eps), Maxiter(Maxiter) {}

    virtual double solve() {
        double x = x0; // 从初始猜测开始
        for (int k = 0; k < Maxiter; ++k) {
            double u = F(x); // 计算函数值

            if (std::abs(u) < eps) { // 如果函数值足够小，退出循环
                return x; // 返回找到的根
            }

            double dfx = F.derivative(x); // 计算导数值
            x = x - u / dfx; // 更新 x 值
        }

        // 如果达到最大迭代次数
        throw std::runtime_error("Maximum iterations reached.");
        return x;
    }
};

class Secant_Method : public EquationSolver {
private:
    double x_0;
    double x_1;
    int Maxiter;
    double delta;
    double eps;
public:
    Secant_Method(const Function &F, double x_0, double x_1,
        int Maxiter = 100, double eps = 1e-7, double delta = 1e-6) : // 修改默认值
        EquationSolver(F), x_0(x_0), x_1(x_1), Maxiter(Maxiter), delta(delta), eps(eps) {}

    virtual double solve() {
        double x_curr = x_1;
        double x_prev = x_0;
        double u = F(x_curr);
        double v = F(x_prev);

        for (int k = 2; k <= Maxiter; ++k) {
            double s = (x_curr - x_prev) / (u - v); // 计算割线斜率
            double x_next = x_curr - u * s; // 计算下一个 x 值

            // 检查收敛条件 |x_next - x_curr| < δ
            if (std::abs(x_next - x_curr) < delta) {
                return x_next; // 收敛，返回结果
            }

            x_prev = x_curr; // 保存当前值
            v = u; // 更新 v
            x_curr = x_next; // 更新 x_curr
            u = F(x_curr); // 更新 u

            // 检查收敛条件 |f(x_curr)| < ε
            if (std::abs(u) < eps) {
                return x_curr; // 收敛，返回结果
            }
        }

        // 如果达到最大迭代次数
        throw std::runtime_error("Max iterations reached.");
        return x_curr;
    }
};

#endif